package server;


import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.UUID;

import common.Level;
import common.PlayerEvent;

public class GameControllerImpl implements GameController {

	
	private GameControllerState state;
	private UpdateableGame game;
	private PlayerFactory playerFactory;
	private Level level;
	private Timer timer;
	private ClientUpdater clientUpdater;
	
	Map<UUID, UpdateablePlayer> players = 
			new HashMap<UUID, UpdateablePlayer>(GameController.MAX_PLAYERS);
	
	public GameControllerImpl(ClientUpdater c) {
		clientUpdater = c;
		playerFactory = new PlayerFactory();
		level = new Level(null);
		playerFactory.setLevel(level);
		game = new UpdateableGameImpl();
		
		state = new GameStateWaitingForPlayers();		
		state.initializeState(this);
	}
	
	
	@Override
	public UpdateableGame getGame() {
		return game;
	}
	
	@Override
	public Level getLevel() {
		return level;
	}
	
	
	@Override
	public void setTimer(long period) {
		if (timer != null) {
			stopTimer();
		}
		timer = new Timer();
		GameTimerTask task = new GameTimerTask();
		task.attach(this);
		timer.schedule(task, period, period);
	}
	
	
	@Override
	public void stopTimer() {
		timer.cancel();
		timer = null;
	}
	
	
	@Override
	public void timerTick(int tick) {
		state.timerTick(tick);

		// propagate changes to client
		clientUpdater.updateClients();
	}
	

	@Override
	public void clientAttached(UUID id, String playerName) {
	
		if (!playerFactory.hasNext()) 
			throw new IllegalStateException("no free player available");
		
		UpdateablePlayer p = playerFactory.getNextPlayer(playerName);
		players.put(id, p);
		game.setPlayer(players.values().toArray(new UpdateablePlayer[0]));
		
		System.out.println("  assign player: " + p);
		
		state.playerAttached(p);
	}

	
	@Override
	public void clientDetached(UUID id) {

		UpdateablePlayer p = players.get(id);
		if (p == null)
			throw new IllegalArgumentException("got unknown user id");
		
		players.remove(id);
		game.setPlayer(players.values().toArray(new UpdateablePlayer[0]));
		playerFactory.releasePlayer(p);
		
		System.out.println("removed player: " + p);
		
		state.playerDetached(p);
		
	}

	
	@Override
	public void playerEvent(UUID id, PlayerEvent event) {
		
		UpdateablePlayer p = players.get(id);
		if (p == null)
			throw new IllegalArgumentException("got unknown user id");
		
		state.playerEvent(p, event);
		
	}

	
	@Override
	public void setState(GameControllerState nextState) {
		state.detachState();
		state = nextState;
		state.initializeState(this);
	}




	
}
